package com.alinesno.cloud.common.core.encoder;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

import feign.RequestTemplate;
import feign.codec.EncodeException;
import feign.codec.Encoder;

/**
 * 添加Pageable接收的支持
 * 
 * @author LuoAnDong
 * @since 2018年12月15日 下午12:59:08
 */
public class PageableQueryEncoder implements Encoder {

	private static final Logger log = LoggerFactory.getLogger(PageableQueryEncoder.class);

	private final Encoder delegate;

	public PageableQueryEncoder(Encoder delegate) {
		this.delegate = delegate;
	}

	@Override
	public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException {

		log.debug("object = {}", ToStringBuilder.reflectionToString(object));
		log.debug("bodytype = {}", ToStringBuilder.reflectionToString(bodyType));
		log.debug("template = {}", ToStringBuilder.reflectionToString(template));

		Map<String, Collection<String>> map = template.queries();
		for (String k : map.keySet()) {
			log.debug("k = {} , v = {}", k, ToStringBuilder.reflectionToString(map.get(k)));
			for (String s : map.get(k)) {
				log.debug("s = {}", ToStringBuilder.reflectionToString(s));
			}
		}

		if (object instanceof Pageable) {

			log.debug("page = {}", ToStringBuilder.reflectionToString(object));

			Pageable pageable = (Pageable) object;
			template.query("page", pageable.getPageNumber() + "");
			template.query("size", pageable.getPageSize() + "");

			if (pageable.getSort() != null) {
				Collection<String> existingSorts = template.queries().get("sort");
				List<String> sortQueries = existingSorts != null ? new ArrayList<>(existingSorts) : new ArrayList<>();
				for (Sort.Order order : pageable.getSort()) {
					sortQueries.add(order.getProperty() + "," + order.getDirection());
				}
				template.query("sort", sortQueries);
			}

		} else {
			delegate.encode(object, bodyType, template);
		}

	}
}